use std::os::raw::{c_int, c_char};
use std::ptr;
use std::ffi::CString;

use ratatui::style::{Color, Style, Modifier};
use crate::RatatuiResult;

/// Color enumeration
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RatatuiColor {
    Reset = 0,
    Black = 1,
    Red = 2,
    Green = 3,
    Yellow = 4,
    Blue = 5,
    Magenta = 6,
    Cyan = 7,
    Gray = 8,
    DarkGray = 9,
    LightRed = 10,
    LightGreen = 11,
    LightYellow = 12,
    LightBlue = 13,
    LightMagenta = 14,
    LightCyan = 15,
    White = 16,
}

impl RatatuiColor {
    pub fn to_ratatui_color(&self) -> Color {
        match self {
            RatatuiColor::Reset => Color::Reset,
            RatatuiColor::Black => Color::Black,
            RatatuiColor::Red => Color::Red,
            RatatuiColor::Green => Color::Green,
            RatatuiColor::Yellow => Color::Yellow,
            RatatuiColor::Blue => Color::Blue,
            RatatuiColor::Magenta => Color::Magenta,
            RatatuiColor::Cyan => Color::Cyan,
            RatatuiColor::Gray => Color::Gray,
            RatatuiColor::DarkGray => Color::DarkGray,
            RatatuiColor::LightRed => Color::LightRed,
            RatatuiColor::LightGreen => Color::LightGreen,
            RatatuiColor::LightYellow => Color::LightYellow,
            RatatuiColor::LightBlue => Color::LightBlue,
            RatatuiColor::LightMagenta => Color::LightMagenta,
            RatatuiColor::LightCyan => Color::LightCyan,
            RatatuiColor::White => Color::White,
        }
    }
}

/// Modifier enumeration
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RatatuiModifier {
    Bold = 1,
    Dim = 2,
    Italic = 4,
    Underlined = 8,
    SlowBlink = 16,
    RapidBlink = 32,
    Reversed = 64,
    CrossedOut = 128,
    Hidden = 256,
}

impl RatatuiModifier {
    pub fn to_ratatui_modifier(&self) -> Modifier {
        match self {
            RatatuiModifier::Bold => Modifier::BOLD,
            RatatuiModifier::Dim => Modifier::DIM,
            RatatuiModifier::Italic => Modifier::ITALIC,
            RatatuiModifier::Underlined => Modifier::UNDERLINED,
            RatatuiModifier::SlowBlink => Modifier::SLOW_BLINK,
            RatatuiModifier::RapidBlink => Modifier::RAPID_BLINK,
            RatatuiModifier::Reversed => Modifier::REVERSED,
            RatatuiModifier::CrossedOut => Modifier::CROSSED_OUT,
            RatatuiModifier::Hidden => Modifier::HIDDEN,
        }
    }
}

/// Theme structure
#[repr(C)]
#[derive(Debug, Clone)]
pub struct RatatuiTheme {
    pub name: String,
    pub primary: RatatuiColor,
    pub secondary: RatatuiColor,
    pub accent: RatatuiColor,
    pub background: RatatuiColor,
    pub text: RatatuiColor,
    pub error: RatatuiColor,
    pub warning: RatatuiColor,
    pub success: RatatuiColor,
}

impl RatatuiTheme {
    pub fn default() -> Self {
        RatatuiTheme {
            name: "Default".to_string(),
            primary: RatatuiColor::Blue,
            secondary: RatatuiColor::Cyan,
            accent: RatatuiColor::Yellow,
            background: RatatuiColor::Black,
            text: RatatuiColor::White,
            error: RatatuiColor::Red,
            warning: RatatuiColor::Yellow,
            success: RatatuiColor::Green,
        }
    }

    pub fn dark() -> Self {
        RatatuiTheme {
            name: "Dark".to_string(),
            primary: RatatuiColor::LightBlue,
            secondary: RatatuiColor::Cyan,
            accent: RatatuiColor::Yellow,
            background: RatatuiColor::Black,
            text: RatatuiColor::White,
            error: RatatuiColor::Red,
            warning: RatatuiColor::Yellow,
            success: RatatuiColor::Green,
        }
    }

    pub fn light() -> Self {
        RatatuiTheme {
            name: "Light".to_string(),
            primary: RatatuiColor::Blue,
            secondary: RatatuiColor::Cyan,
            accent: RatatuiColor::Magenta,
            background: RatatuiColor::White,
            text: RatatuiColor::Black,
            error: RatatuiColor::Red,
            warning: RatatuiColor::Yellow,
            success: RatatuiColor::Green,
        }
    }
}

/// Create a new style
#[no_mangle]
pub extern "C" fn ratatui_style_new() -> *mut Style {
    let style = Style::default();
    Box::into_raw(Box::new(style))
}

/// Free a style
#[no_mangle]
pub extern "C" fn ratatui_style_free(style: *mut Style) {
    if !style.is_null() {
        unsafe {
            let _ = Box::from_raw(style);
        }
    }
}

/// Set foreground color
#[no_mangle]
pub extern "C" fn ratatui_style_set_fg(style: *mut Style, color: RatatuiColor) -> c_int {
    if style.is_null() {
        return RatatuiResult::ErrorNullPointer as c_int;
    }

    unsafe {
        let style_ref = &mut *style;
        *style_ref = style_ref.fg(color.to_ratatui_color());
        RatatuiResult::Ok as c_int
    }
}

/// Set background color
#[no_mangle]
pub extern "C" fn ratatui_style_set_bg(style: *mut Style, color: RatatuiColor) -> c_int {
    if style.is_null() {
        return RatatuiResult::ErrorNullPointer as c_int;
    }

    unsafe {
        let style_ref = &mut *style;
        *style_ref = style_ref.bg(color.to_ratatui_color());
        RatatuiResult::Ok as c_int
    }
}

/// Add modifier
#[no_mangle]
pub extern "C" fn ratatui_style_add_modifier(style: *mut Style, modifier: RatatuiModifier) -> c_int {
    if style.is_null() {
        return RatatuiResult::ErrorNullPointer as c_int;
    }

    unsafe {
        let style_ref = &mut *style;
        *style_ref = style_ref.add_modifier(modifier.to_ratatui_modifier());
        RatatuiResult::Ok as c_int
    }
}

/// Remove modifier
#[no_mangle]
pub extern "C" fn ratatui_style_remove_modifier(style: *mut Style, modifier: RatatuiModifier) -> c_int {
    if style.is_null() {
        return RatatuiResult::ErrorNullPointer as c_int;
    }

    unsafe {
        let style_ref = &mut *style;
        *style_ref = style_ref.remove_modifier(modifier.to_ratatui_modifier());
        RatatuiResult::Ok as c_int
    }
}

/// Create default theme
#[no_mangle]
pub extern "C" fn ratatui_theme_default() -> *mut RatatuiTheme {
    let theme = RatatuiTheme::default();
    Box::into_raw(Box::new(theme))
}

/// Create dark theme
#[no_mangle]
pub extern "C" fn ratatui_theme_dark() -> *mut RatatuiTheme {
    let theme = RatatuiTheme::dark();
    Box::into_raw(Box::new(theme))
}

/// Create light theme
#[no_mangle]
pub extern "C" fn ratatui_theme_light() -> *mut RatatuiTheme {
    let theme = RatatuiTheme::light();
    Box::into_raw(Box::new(theme))
}

/// Free theme
#[no_mangle]
pub extern "C" fn ratatui_theme_free(theme: *mut RatatuiTheme) {
    if !theme.is_null() {
        unsafe {
            let _ = Box::from_raw(theme);
        }
    }
}

/// Get theme color
#[no_mangle]
pub extern "C" fn ratatui_theme_get_color(theme: *const RatatuiTheme, color_type: c_int) -> RatatuiColor {
    if theme.is_null() {
        return RatatuiColor::White;
    }

    unsafe {
        let theme_ref = &*theme;
        match color_type {
            0 => theme_ref.primary,
            1 => theme_ref.secondary,
            2 => theme_ref.accent,
            3 => theme_ref.background,
            4 => theme_ref.text,
            5 => theme_ref.error,
            6 => theme_ref.warning,
            7 => theme_ref.success,
            _ => RatatuiColor::White,
        }
    }
}

/// Get theme name
#[no_mangle]
pub extern "C" fn ratatui_theme_get_name(theme: *const RatatuiTheme) -> *mut c_char {
    if theme.is_null() {
        return ptr::null_mut();
    }

    unsafe {
        let theme_ref = &*theme;
        match CString::new(theme_ref.name.clone()) {
            Ok(c_string) => c_string.into_raw(),
            Err(_) => ptr::null_mut(),
        }
    }
}
